package com.hooker.hook;

import android.content.Context;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.hooker.base.BaseHooker;
import com.hooker.settings.SettingHelper;
import com.hooker.util.Constants;

import java.util.ArrayList;
import java.util.List;

import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.callbacks.XC_LoadPackage;

public class RuleHooker extends BaseHooker {

    private RuleHooker() {

    }

    public RuleHooker(Context context, XC_LoadPackage.LoadPackageParam lparam) {
        super(context, lparam);
    }

    private static class Instance {
        private static final RuleHooker singleton = new RuleHooker();
    }

    public static synchronized RuleHooker getInstance() {
        return Instance.singleton;
    }

    public RuleHookListener getListener(){
        return listener;
    }

    private static RuleHookListener listener = new RuleHookListener() {
        @Override
        public void addRule(Context context, Rule rule) {
            if (context != null && rule != null) {
                SettingHelper.putInfo(context, getInstance().getTag(), rule.toString());
            }
        }

        @Override
        public void handle(Context context, final Rule rule, XC_LoadPackage.LoadPackageParam lparam) {
            try {
                List<String> params = rule.getParams();
                getInstance().hookMethod(rule.getClassName(), rule.getMethod(), params.toArray(new String[params.size()]), new XC_MethodHook() {
                    @Override
                    protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                        super.beforeHookedMethod(param);
                        getInstance().log("rule.name=" + rule.getName() + ": " + concatParams(param));
                    }

                    @Override
                    protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                        super.afterHookedMethod(param);
                    }
                });
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    };


    @Override
    public void hook(Object... calls) {
        List<String> list = SettingHelper.getInfo(context, getTag());

        List<Rule> rules = new ArrayList<>();
        for (String s : list) {
            Rule rule = new Gson().fromJson(s, new TypeToken<Rule>() {
            }.getType());
            if (rule != null) {
                rule.update();
                rules.add(rule);
            }
        }

        for (final Rule rule : rules) {
            listener.handle(context, rule, loadParams);
        }
    }

    @Override
    public String getTag() {
        return Constants.RULE_TAG_ID;
    }


}
